#version 440 core

#define GRID_SIZE_X 64
#define GRID_SIZE_Y 64

layout(local_size_x=128) in;

layout(binding=1, r32i) uniform readonly iimage2D nodeIndexImage;

layout(binding=3) coherent buffer nodePositionBuffer {
	uvec2 nodePositions[];
};

layout(binding=4) coherent buffer nodeNeighborhoodBuffer {
	int nodeNeighborhood[];
};

uniform uint numFemNodes;

bool outOfBounds(ivec2 p)
{
	return p.x == -1
		|| p.x == GRID_SIZE_X+1
		|| p.y == -1
		|| p.y == GRID_SIZE_Y+1;
}

void main(void)
{
	uint nodeID = gl_GlobalInvocationID.x;
	if (nodeID < numFemNodes)
	{
		ivec2 pos = ivec2(nodePositions[nodeID]);

		nodeNeighborhood[nodeID*9] = int(nodeID);

		ivec2 opos = pos+ivec2(-1,-1);
		nodeNeighborhood[nodeID*9+1] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));

		opos = pos+ivec2(0,-1);
		nodeNeighborhood[nodeID*9+2] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));

		opos = pos+ivec2(1,-1);
		nodeNeighborhood[nodeID*9+3] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));

		opos = pos+ivec2(1,0);
		nodeNeighborhood[nodeID*9+4] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));

		opos = pos+ivec2(1,1);
		nodeNeighborhood[nodeID*9+5] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));

		opos = pos+ivec2(0,1);
		nodeNeighborhood[nodeID*9+6] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));

		opos = pos+ivec2(-1,1);
		nodeNeighborhood[nodeID*9+7] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));

		opos = pos+ivec2(-1,0);
		nodeNeighborhood[nodeID*9+8] = int(mix(imageLoad(nodeIndexImage, opos).x, -2, outOfBounds(opos)));
	}
}